﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.ComponentModel.Design;
using System.Collections;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;

namespace WfDesignControl
{
    public partial class WFDesignControl : UserControl, IDisposable, IServiceProvider, ISite
    {
        private WorkflowView workflowView;
        private DesignSurface designSurface;
        public WFLoader loader;
        private WFLoader _wfLoader = new WFLoader();
        private TypeProvider _typeProvider;
        private Control _toolboxControl;

        public WorkflowView WorkflowView
        {
            get { return this.workflowView; }
        }

        public Control ToolboxControl
        {
            get { return _toolboxControl; }
        }

        public TypeProvider TypeProvider
        {
            get { return _typeProvider; }
            set
            {
                _typeProvider = value;
                //pass the TypeProvider to the loader
                _wfLoader.TypeProvider = _typeProvider;
            }
        }

        public WFDesignControl()
        {
            InitializeComponent();

            ToolboxService toolbox = new ToolboxService(this);
            this.panel1.Controls.Add(toolbox);
            toolbox.Dock = DockStyle.Top;
            toolbox.BackColor = BackColor;
            toolbox.Font = WorkflowTheme.CurrentTheme.AmbientTheme.Font;

            //WorkflowTheme为工作流提供外观属性设置
            //AmbientTheme为设计时环境中的顶级工作流提供外观属性设置
            WorkflowTheme.CurrentTheme.ReadOnly = false;
            WorkflowTheme.CurrentTheme.AmbientTheme.ShowConfigErrors = false;
            WorkflowTheme.CurrentTheme.ReadOnly = true;

            this.propertyGrid.BackColor = BackColor;
            this.propertyGrid.Font = WorkflowTheme.CurrentTheme.AmbientTheme.Font;
            this.propertyGrid.Site = this;
        }

        public void LoadWorkflow(string XomlFileName)
        {
            string xoml = string.Empty;
            string rules = string.Empty;
            string layout = string.Empty;

            using (System.IO.StreamReader sr = new StreamReader(XomlFileName))
            {
                xoml = sr.ReadToEnd();
                //mlh 2011-11-21 +加入状态机的限制（条件：只要字符串里存在  BaseStateWorkflow  就允许继续加载该文件，否则返回
                if (!xoml.Contains("BaseStateWorkflow")) return;
            }
            if (System.IO.File.Exists(XomlFileName.ToLower().Replace(".xoml", ".rules")))
            {
                using (System.IO.StreamReader sr = new StreamReader(XomlFileName.ToLower().Replace(".xoml", ".rules")))
                {
                    rules = sr.ReadToEnd();
                }
            }
            if (System.IO.File.Exists(XomlFileName.ToLower().Replace(".xoml", ".layout")))
            {
                using (System.IO.StreamReader sr = new StreamReader(XomlFileName.ToLower().Replace(".xoml", ".layout")))
                {
                    layout = sr.ReadToEnd();
                }
            }
            LoadWorkflow(xoml, rules, layout, XomlFileName);
        }

        public void LoadWorkflow(string xoml, string rules, string Layout, string XomlFile)
        {
            SuspendLayout();

            DesignSurface designSurface = new DesignSurface();
            WFLoader loader = new WFLoader();
            loader.Xoml = xoml;
            loader.Rules = rules;
            loader.Layout = Layout;
            loader.XomlFile = XomlFile;
            designSurface.BeginLoad(loader);

            IDesignerHost designerHost = designSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (designerHost != null && designerHost.RootComponent != null)
            {
                IRootDesigner rootDesigner = designerHost.GetDesigner(designerHost.RootComponent) as IRootDesigner;
                if (rootDesigner != null)
                {
                    UnloadWorkflow();

                    this.designSurface = designSurface;
                    this.loader = loader;
                    this.workflowView = rootDesigner.GetView(ViewTechnology.Default) as WorkflowView;
                    //this.workflowView = designSurface.View as WorkflowView
                    //将显示面加入
                    this.wfSplitContainer.Panel1.Controls.Add(this.workflowView);
                    this.workflowView.Dock = DockStyle.Fill;

                    this.workflowView.TabIndex = 1;
                    this.workflowView.TabStop = true;
                    this.workflowView.HScrollBar.TabStop = false;
                    this.workflowView.VScrollBar.TabStop = false;
                    this.workflowView.Focus();
                    this.propertyGrid.Site = designerHost.RootComponent.Site;

                    ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
                    if (selectionService != null)
                        selectionService.SelectionChanged += new EventHandler(selectionService_SelectionChanged);
                }
            }

            ResumeLayout(true);
        }

        public void Save(string filePath)
        {
            if (this.loader != null)
            {
                if (filePath != null && filePath != string.Empty)
                    this.loader.XomlFile = filePath;
                this.loader.Save();
            }
        }

        void selectionService_SelectionChanged(object sender, EventArgs e)
        {
            ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
            if (selectionService != null)
                this.propertyGrid.SelectedObjects = new ArrayList(selectionService.GetSelectedComponents()).ToArray();
        }

        public void InvokeStandardCommand(CommandID cmd)
        {
            IMenuCommandService menuService = GetService(typeof(IMenuCommandService)) as IMenuCommandService;
            if (menuService != null)
                menuService.GlobalInvoke(cmd);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                UnloadWorkflow();
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region 接口成员

        public new object GetService(Type serviceType)
        {
            return (this.workflowView != null) ? ((IServiceProvider)this.workflowView).GetService(serviceType) : null;
        }

        public IComponent Component
        {
            get { return this; }
        }

        public new bool DesignMode
        {
            get { return true; }
        }

        #endregion

        private void UnloadWorkflow()
        {
            IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost;
            if (designerHost != null && designerHost.Container.Components.Count > 0)
                WFLoader.DestroyObjectGraphFromDesignerHost(designerHost, designerHost.RootComponent as Activity);

            ISelectionService selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
            if (selectionService != null)
                selectionService.SelectionChanged -= new EventHandler(selectionService_SelectionChanged);

            if (this.designSurface != null)
            {
                this.designSurface.Dispose();
                this.designSurface = null;
            }

            if (this.workflowView != null)
            {
                Controls.Remove(this.workflowView);
                this.workflowView.Dispose();
                this.workflowView = null;
            }
        }

        public bool Validate()
        {
            IDesignerHost designerHost = GetService(typeof(IDesignerHost)) as IDesignerHost;
            return WFLoader.Validate(designerHost.RootComponent as CompositeActivity);
        }

    }
}
